FORMAT: 1A

# libStorage
`libStorage` provides a vendor agnostic storage orchestration model, API, and
reference client and server implementations.

## Headers
The libStorage API supports custom headers for sending information
about a client's instance ID and local devices as well as other
pieces of data.

### Request Headers
libStorage supports the following request headers:

Name | Description
-----|------------
`Libstorage-Instanceid` | A client's instance ID
`Libstorage-Localdevices` | The client's local device map
`Libstorage-Txid` | A transaction ID
`Libstorage-Txcr` | The timestamp (epoch) at which the transaction was created.

Please note the header names are case sensitive and must comply with the above,
listed values. This is in adherence to the
[canonical header](https://golang.org/pkg/net/http/#CanonicalHeaderKey) format.

<a name="def-instance-id"></a>
#### Instance ID
A client's instance ID must be provided to the remote libStorage
server in order for certain storage operations to succeed. Because
there are API operations using the GET method, a header is the only
logical choice for encapsulating the instance ID.

The name of the header is `Libstorage-Instanceid` and it adheres to
the following format:

```
Libstorage-Instanceid: DRIVER[:SERVICE]=ID,FIELDS,METADATA
```

The header's value is made up of several pieces of information, as
illustrated in the above example format:

 Name | Description
------|------------
`DRIVER[:SERVICE]` | The name of the driver for which the instance ID is intended. An optional suffix of `:SERVICE` may also be present where `SERVICE` is the name of the service for which the instance ID is valid. This format takes precedence over another instance ID specified only by `DRIVER` type.
`ID`  | The instance ID. This is a string value.
`FIELDS` | A URL-encoded string of key-value pairs.
`METADATA` | A base-64 encoded buffer that can be used to transport temporary "seed" data to a driver's `InstanceInspect` function in order to generate the real instance ID.

The following is an example of headers for sending
instance ID information generated by EBS and EFS:

```
Libstorage-Instanceid: ebs=i-1234,region=west
Libstorage-Instanceid: ebs:ebs-00=i-5678,region=west
Libstorage-Instanceid: efs=i-1234,region%3Deast%2Czone%3D2
```

The first instance ID header is valid for all services
that use the `ebs` driver. However, because the second
instance ID specifies the service name `ebs-00`, the
second instance ID is used for that service in place
of the first, even though the first is valid for the
`ebs` driver type.

Notice that the instance ID for the EFS driver contains
encoded characters. That's because the `FIELDS` component
of an instance ID is URL encoded like a query string in
order to escape `=` and `,` characters.

The instance ID's `METADATA` component is temporary and
used only by storage platforms that are not able to fully
generate an instance ID on the client-side. For example,
the ScaleIO platform generates the client's ScaleIO GUID
and uses the libStorage server's `InstanceInspect` API
to build the actual instance ID. Thus the initial instance
ID might be sent as :

```
Libstorage-Instanceid: scaleio=,,MWJiOTFmMDctODU2ZC00YWY5LWFjZWQtM2UzZmMzOTY0MDU5
```

The above instance ID lacks an actual ID and any fields. The only data
present is the `METADATA`, a base-64 encoded value that the remote
storage driver knows how to unmarshal.

On the server-side the ScaleIO driver would take the metadata and use
it to generate the actual instance ID, responding to the client with
a response header:

```
Libstorage-Instanceid: scaleio=client-123
```

Subsequent calls from the client to the server would then use the
fully-formed instance ID where required.

Please note that the `InstanceInspect` call will also return any
`FIELD` data in the response header. Only the `METADATA` is stripped.

<a name="def-local-devices"></a>
#### Local Devices
The client must also transmit information about its local devices. The
header adheres to the following format:

```
Libstorage-Localdevices: DRIVER=VOLUME_ID::DEVICE_PATH[,VOLUME_ID::DEVICE_PATH,...]
```

Name | Description
------|------------
`DRIVER` | The driver for which the local devices map is intended.
`VOLUME_ID`  | A piece of information obtainable on the client that can be used on the server-side to identify a volume.
`DEVICE_PATH` | The path to the device on the client at which the volume is attached.

The following is an example of headers for sending
local device maps generated by EBS and ScaleIO:

```
Libstorage-Localdevices: ebs=/dev/xvdf::/dev/xvdf,/dev/xvdg::/dev/xvdg
Libstorage-Localdevices: scaleio=vol-1235::/dev/scini1,vol-8973::/dev/scini2
```

Note that the EBS driver's local device map appears to be incorrect with
the `DEVICE_PATH` used as the `VOLUME_ID` key. Some drivers, such as EBS,
actually provide a device path at the time a volume is attached, meaning
that the remote storage platform can map a volume based on a provided
device path. Thus for the EBS platform the device path is the piece of
information used to map to a remote volume as well as the path to which
said volume is attached as a device on a given client.

This is in contrast to to the ScaleIO local devices map which uses
volume IDs unrelated to the device at which a volume is attached.

#### Transaction ID
The transaction ID is a UUID/GUID that is used to track an operation
from the time it originates on a client, through the server, and back
to the client again. The header name is `Libstorage-Txid`:

```
Libstorage-Txid: 959716fa-6a76-4e48-6243-1dd328c0f313
```

#### Transaction Created
The header `Libstorage-Txcr` is a UTC epoch timestamp that notes when
the original client-side operation was created:

```
Libstorage-Txcr: 1461644872
```

### Response Headers
libStorage supports the following response headers:

Name | Description
-----|------------
`Libstorage-Instanceid` | A client's instance ID.
`Libstorage-Servername` | The server's name.

Please note the header names are case sensitive and must comply with the above,
listed values. This is in adherence to the
[canonical header](https://golang.org/pkg/net/http/#CanonicalHeaderKey) format.

#### Instance ID (Response)
Please see [this section](#def-instance-id) for more information.

#### Server Name
The `Libstorage-Servername` header is returned with every response for
clients that use it for logging purposes.

## Security
The libStorage API is primarily hosted via HTTP-REST and therefore
an HTTP proxy such as [NGINX](https://www.nginx.com) can be leveraged
to provide security features such as authentication and authorization.

In the absence of an HTTP proxy, software that implements the
libStorage API should also support
[JSON Web Tokens (JWT)](https://jwt.io/) to restrict access to
API resources.

The payload of the libStorage API's JWT follows the below format:

```
{
  "exp": 1493592581,
  "iat": 1491000581,
  "nbf": 1491000581,
  "sub": "akutz",
}
```

The above payload's claims (fields) are:

Name | Description
-----|------------
`exp` | The time at which the token expires. A value of `0` means the token does not expire.
`iat` | The time at which the token was issued.
`nbf` | The time at which the token becomes valid.
`sub` | The principal for whom the token is intended.

All of the above time values are specified as UTC epochs in seconds.

A client transmits the JWT as a
[_Bearer_](https://tools.ietf.org/html/rfc6750#section-2.1)
token in the HTTP `Authorization` header. For example:

```
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1MjI2ODg1NTAsImlhdCI6MTQ5MTIzODk1MCwibmJmIjoxNDkxMjM4OTUwLCJzdWIiOiJha3V0eiJ9.3eAA7AQZUGrwA42H64qKbu8QF_AHpSsJSMR0FALnKj8
```

If the provided token is invalid then the libStorage server should return an
HTTP status of 401, _Unauthorized_.

Implementations of the libStorage API should support restricting access via
JWTs both globally and per configured service.

If a `GET /volumes` request is issued and the provided token lacks access to
one of the services, a 401 `Unauthorized` status will be returned instead of a
partial dataset.

# Group Root

# Root Resource [/]
The root resource.

## Get [GET]
Gets a list of the API's top-level resources.

+ Response 200 (application/json)

    + Body

            [
                "/services",
                "/volumes",
                "/snapshots"
            ]

# Group Services

# Services Collection [/services?{instance}]

## Get [GET]
Gets information about all of the configured services.

+ Parameters

    + instance: `false` (boolean, optional)

            When the instance query string is specified the instance ID header
            is required. This flag indicates that the services' instances should
            be retrieved along with standard service information.

+ Response 200 (application/json)

    + Body

            {
                "ebs-00": {
                    "name": "ebs-00",
                    "driver": {
                        "name": "ebs",
                        "type": "block"
                    }
                }
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/serviceInfoMap" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }

# Service Inspector [/services/{service}?{instance}]

+ Parameters

    + service: `ebs-00` (string, required)
    + instance: `false` (boolean, optional)

            When the instance query string is specified the instance ID header
            is required. This flag indicates that the service's instance should
            be retrieved along with standard service information.

## Inspect [GET]
Gets information about the service with the specified name.

+ Response 200 (application/json)

    + Attributes (ServiceInfo)

    + Body

            {
                "name": "ebs-00",
                "driver": {
                    "name": "ebs",
                    "type": "block"
                }
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/serviceInfo" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 404 (application/json)
The specified resource was not found

    + Body

            {
                "type":      "resourceNotFound",
                "httpStatus": 404,
                "message":   "The requested resource was not found"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/resourceNotFoundError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }

# Group Volumes
A collection of resources and actions related to libStorage Volumes.

# Volumes Collection [/volumes]
A collection of Volume objects for all configured services.

## Get [GET /volumes]
Gets a list of Volume resources for all configured services.

+ Response 200 (application/json)

    + Body

            {
                "ebs-00": {
                    "vol-000": {
                        "id":     "vol-000",
                        "name":   "Volume-000",
                        "size":   10240,
                        "fields": {
                            "priority": 2,
                            "owner":    "sakutz@gmail.com"
                        }
                    },
                    "vol-001": {
                        "id":     "vol-001",
                        "name":   "Volume-001",
                        "size":   10240,
                        "fields": {
                            "priority": 2,
                            "owner":    "sakutz@gmail.com"
                        }
                    }
                },
                "ebs-01": {
                    "vol-000": {
                        "id":     "vol-000",
                        "name":   "Volume-000",
                        "size":   10240,
                        "fields": {
                            "priority": 2,
                            "owner":    "sakutz@gmail.com"
                        }
                    }
                }
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/serviceVolumeMap" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }

## Get with Attachments [GET /volumes?{attachments}]
Gets a list of Volume resources and their attached resources for all configured
services.

+ Parameters

    + attachments (string,optional)

        A value that indicates how and if volume attachments should be retrieved.
        <br/><br/>
        The `attachments` parameter can be any of the following values:
        <br/>
        Value | Description
        ------|------------
        0 | No attachment information is requested. This is the default value and the same as omitting this parameter altogether.
        1 | Attachment information is requested. This value indicates attachment information should be returned for all volumes.
        2 | _My_ attachment information is requested. This value indicates attachment information should be returned for volumes attached to the instance specified in the [instance ID request header](#def-instance-id). If this bit is set then the instance ID header is required.
        4 | Attempt to map devices provided via the [local devices](#def-local-devices) request header to the appropriate attachment information. If this bit is set then the instance ID and local device headers are required.
        8 | Return only volumes that are attached.
        16 | Return only volumes that are unattached.
        <br/><br/>
        The use of a bitmask for the `attachments` parameter means that
        different combinations of the above values can be used to
        indicate different results:
        <br/>
        Mask | Description
        -----|------------
        5 | A mask of `1|4` that indicates to return all volumes with their attachment data (if any) and perform a device mapping where possible.
        9 | A mask of `1|8` that indicates to return only volumes that are attached to some instance.
        10 | A mask of `2|8` that indicates to return only volumes attached to the instance provided via the instance ID header.

+ Request

    + Headers

            Libstorage-Instanceid: ebs-00=i-123,region%3Dwest,ebs-01:eyJpZCI6ImlpZC0wMDEiLCJtZXRhZGF0YSI6eyJtYXgiOjIwLCJtaW4iOjUsInJhZCI6ImhvdCJ9fQ==

+ Response 200 (application/json)

    + Body

            {
                "ebs-00": {
                    "vol-000": {
                        "id":     "vol-000",
                        "name":   "Volume-000",
                        "size":   10240,
                        "attachments": [
                            {
                                "instanceID": {
                                   "id": "iid-000"
                                },
                                "volumeID": "vol-000",
                                "deviceName": "/dev/xvd00"
                            }
                        ],
                        "fields": {
                            "priority": 2,
                            "owner":    "sakutz@gmail.com"
                        }
                    },
                    "vol-001": {
                        "id":     "vol-001",
                        "name":   "Volume-001",
                        "size":   10240,
                        "attachments": [
                            {
                                "instanceID": {
                                   "id": "iid-001"
                                },
                                "volumeID": "vol-001",
                                "deviceName": "/dev/xvd01"
                            }
                        ],
                        "fields": {
                            "priority": 2,
                            "owner":    "sakutz@gmail.com"
                        }
                    }
                },
                "ebs-01": {
                    "vol-000": {
                        "id":     "vol-000",
                        "name":   "Volume-000",
                        "size":   10240,
                        "attachments": [
                            {
                                "instanceID": {
                                   "id": "iid-000"
                                },
                                "volumeID": "vol-000",
                                "deviceName": "/dev/xvd00"
                            }
                        ],
                        "fields": {
                            "priority": 2,
                            "owner":    "sakutz@gmail.com"
                        }
                    }
                }
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/serviceVolumeMap" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }

## Detach All [POST /volumes?{detach}]
Detaches all volumes for all services.

+ Parameters

    + detach (required)

        A flag indicating that the detach operation should be issued for
        all volumes across all configured services.

+ Request (application/json)

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/volumeDetachAllRequest" }

+ Response 200 (application/json)
A list of the detached volumes.

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/serviceVolumeMap" }

+ Response 400 (application/json)
Invalid request

    + Body

            {
                "type":      "invalidRequest",
                "httpStatus": 400,
                "message":   "An invalid request was made"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/invalidRequestError" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }

# Volumes by Service Collection [/volumes/{service}]

+ Parameters

    + service: `ebs-00` (string, required)

        The service name

## Get [GET]
Gets a list of Volume objects for a single Service resource.

+ Response 200 (application/json)

    + Body

            {
                "vol-000": {
                    "id":     "vol-000",
                    "name":   "Volume-000",
                    "size":   10240,
                    "fields": {
                        "priority": 2,
                        "owner":    "sakutz@gmail.com"
                    }
                },
                "vol-001": {
                    "id":     "vol-001",
                    "name":   "Volume-001",
                    "size":   10240,
                    "fields": {
                        "priority": 2,
                        "owner":    "sakutz@gmail.com"
                    }
                }
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/volumeMap" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }

## Get with Attachments [GET /volumes/{service}?{attachments}]
Gets a list of Volume resources and their attached resources for a single
service.

+ Parameters

    + service: `ebs-00` (string, required)

        The service name

    + attachments (string,optional)

        A value that indicates how and if volume attachments should be retrieved.
        <br/><br/>
        The `attachments` parameter can be any of the following values:
        <br/>
        Value | Description
        ------|------------
        0 | No attachment information is requested. This is the default value and the same as omitting this parameter altogether.
        1 | Attachment information is requested. This value indicates attachment information should be returned for all volumes.
        2 | _My_ attachment information is requested. This value indicates attachment information should be returned for volumes attached to the instance specified in the [instance ID request header](#def-instance-id). If this bit is set then the instance ID header is required.
        4 | Attempt to map devices provided via the [local devices](#def-local-devices) request header to the appropriate attachment information. If this bit is set then the instance ID and local device headers are required.
        8 | Return only volumes that are attached.
        16 | Return only volumes that are unattached.
        <br/><br/>
        The use of a bitmask for the `attachments` parameter means that
        different combinations of the above values can be used to
        indicate different results:
        <br/>
        Mask | Description
        -----|------------
        5 | A mask of `1|4` that indicates to return all volumes with their attachment data (if any) and perform a device mapping where possible.
        9 | A mask of `1|8` that indicates to return only volumes that are attached to some instance.
        10 | A mask of `2|8` that indicates to return only volumes attached to the instance provided via the instance ID header.

+ Request

    + Headers

            Libstorage-Instanceid: ebs-00=i-123,region%3Dwest

+ Response 200 (application/json)

    + Body

            {
                "vol-000": {
                    "id":     "vol-000",
                    "name":   "Volume-000",
                    "size":   10240,
                    "attachments": [
                        {
                            "instanceID": {
                               "id": "iid-000"
                            },
                            "volumeID": "vol-000",
                            "deviceName": "/dev/xvd00"
                        }
                    ],
                    "fields": {
                        "priority": 2,
                        "owner":    "sakutz@gmail.com"
                    }
                },
                "vol-001": {
                    "id":     "vol-001",
                    "name":   "Volume-001",
                    "size":   10240,
                    "attachments": [
                        {
                            "instanceID": {
                               "id": "iid-001"
                            },
                            "volumeID": "vol-001",
                            "deviceName": "/dev/xvd01"
                        }
                    ],
                    "fields": {
                        "priority": 2,
                        "owner":    "sakutz@gmail.com"
                    }
                }
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/serviceVolumeMap" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }

## Create [POST]
Create a new volume.

+ Request (application/json)

    + Attributes

        + name (string, required) - The volume name
        + availabilityZone (string, optional) - The zone for which the volume is available
        + encrypted (boolean, optional) - A flag that indicates whether or not to request volume encryption.
        + encryptionKey (string, optional) - The encryption key to use when encrypting the volume.
        + iops (number, optional) - The volume IOPs
        + size (number, optional) - The volume size (GB)
        + type (string, optional) - The volume type
        + opts (object) - Optional request data

    + Body

            {
                "name": "Volume-001",
                "size": 10240,
                "opts": {
                    "priority": 2,
                    "owner":    "sakutz@gmail.com"
                }
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/volumeCreateRequest" }

+ Response 200 (application/json)
The newly created volume object.

    + Attributes (Volume)

    + Headers

            Location: /volumes/ebs-00/vol-001

    + Body

            {
                "id":     "vol-001",
                "name":   "Volume-001",
                "size":   10240,
                "fields": {
                    "priority": 2,
                    "owner":    "sakutz@gmail.com"
                }
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/volume" }

+ Response 400 (application/json)
Invalid request

    + Body

            {
                "type":      "invalidRequest",
                "httpStatus": 400,
                "message":   "An invalid request was made"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/invalidRequestError" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 404 (application/json)
The specified resource was not found

    + Body

            {
                "type":      "resourceNotFound",
                "httpStatus": 404,
                "message":   "The requested resource was not found"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/resourceNotFoundError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }

## Detach All [POST /volumes/{service}?{detach}]
Detaches all volumes for all services.

+ Parameters

    + service: `ebs-00` (string, required)

        The service name

    + detach (required)

        A flag indicating that the detach operation should be issued for
        all volumes for the specified service.

+ Request (application/json)

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/volumeDetachAllRequest" }

+ Response 200 (application/json)
A list of the detached volumes.

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/serviceVolumeMap" }

+ Response 400 (application/json)
Invalid request

    + Body

            {
                "type":      "invalidRequest",
                "httpStatus": 400,
                "message":   "An invalid request was made"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/invalidRequestError" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }

## Volume Inspector [/volumes/{service}/{volumeID}?{attachments}]
A single Volume object. A central part of the libStorage
API, a Volume resource represents a storage volume.

+ Parameters

    + service: `ebs-00` (string, required)

        The name of the service to which the Volume belongs

    + volumeID: `vol-000` (string, required)

        The volume's unique ID

    + attachments (string,optional)

        A value that indicates how and if volume attachments should be retrieved.
        <br/><br/>
        The `attachments` parameter can be any of the following values:
        <br/>
        Value | Description
        ------|------------
        0 | No attachment information is requested. This is the default value and the same as omitting this parameter altogether.
        1 | Attachment information is requested. This value indicates attachment information should be returned for all volumes.
        2 | _My_ attachment information is requested. This value indicates attachment information should be returned for volumes attached to the instance specified in the [instance ID request header](#def-instance-id). If this bit is set then the instance ID header is required.
        4 | Attempt to map devices provided via the [local devices](#def-local-devices) request header to the appropriate attachment information. If this bit is set then the instance ID and local device headers are required.
        8 | Return only volumes that are attached.
        16 | Return only volumes that are unattached.
        <br/><br/>
        The use of a bitmask for the `attachments` parameter means that
        different combinations of the above values can be used to
        indicate different results:
        <br/>
        Mask | Description
        -----|------------
        5 | A mask of `1|4` that indicates to return all volumes with their attachment data (if any) and perform a device mapping where possible.
        9 | A mask of `1|8` that indicates to return only volumes that are attached to some instance.
        10 | A mask of `2|8` that indicates to return only volumes attached to the instance provided via the instance ID header.


### Get [GET]
Retrieves a single volume.

If the `Libstorage-Instanceid` header is provided the volume's attachments are
also retrieved. Unlike when retrieving Volume collections, there's no need to
specify the `attachments` query parameter to request their retrieval.

+ Request

    + Headers

            Libstorage-Instanceid: ebs-00=i-123,region%3Dwest


+ Response 200 (application/json)

    + Attributes (Volume)

    + Body

            {
                "id":     "vol-000",
                "name":   "Volume-000",
                "size":   10240,
                "attachments": [
                    {
                        "instanceID": {
                           "id": "iid-000"
                        },
                        "volumeID": "vol-000",
                        "deviceName": "/dev/xvd00"
                    }
                ],
                "fields": {
                    "priority": 2,
                    "owner":    "sakutz@gmail.com"
                }
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/volume" }

+ Response 400 (application/json)
Invalid request

    + Body

            {
                "type":      "invalidRequest",
                "httpStatus": 400,
                "message":   "An invalid request was made"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/invalidRequestError" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 404 (application/json)
The specified resource was not found

    + Body

            {
                "type":      "resourceNotFound",
                "httpStatus": 404,
                "message":   "The requested resource was not found"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/resourceNotFoundError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }

### Copy [POST /volumes/{service}/{volumeID}?{copy}]
Copies the volume.

+ Parameters

    + service: `ebs-00` (string, required)

        The name of the service to which the Volume belongs

    + volumeID: `vol-000` (string, required)

        The volume's unique ID

    + copy (required)

        The operation flag indicating the copy operation

+ Request (application/json)

    + Body

            {
                "name": "Copy of Volume-000"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/volumeCopyRequest" }

+ Response 200 (application/json)

    + Attributes (Volume)

    + Body

            {
                "id":     "vol-002",
                "name":   "Copy of Volume-000",
                "size":   10240,
                "fields": {
                    "priority": 2,
                    "owner":    "sakutz@gmail.com"
                }
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/volume" }

+ Response 400 (application/json)
Invalid request

    + Body

            {
                "type":      "invalidRequest",
                "httpStatus": 400,
                "message":   "An invalid request was made"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/invalidRequestError" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 404 (application/json)
The specified resource was not found

    + Body

            {
                "type":      "resourceNotFound",
                "httpStatus": 404,
                "message":   "The requested resource was not found"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/resourceNotFoundError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }

### Snapshot [POST /volumes/{service}/{volumeID}?{snapshot}]
Takes a snapshot of the volume.

+ Parameters

    + service: `ebs-00` (string, required)

        The name of the service to which the Volume belongs

    + volumeID: `vol-000` (string, required)

        The volume's unique ID

    + snapshot (required)

        The operation flag indicating the snapshot operation

+ Request (application/json)

    + Attributes

        + snapshotName (string, required) - The name of the snapshot
        + opts (object) - Optional request data

    + Body

            {
                "snapshotName": "Snapshot-000"
            }

+ Response 200 (application/json)

    + Attributes (Snapshot)

    + Body

            {
                "id":           "snap-000",
                "name":         "Snapshot-000",
                "description":  "A snapshot of Volume-000 (vol-000)",
                "startTime":    1455826676,
                "volumeID":     "vol-000",
                "volumeSize":   10240,
                "fields":       {
                    "sparse":   true,
                    "region":   "US"
                }
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/snapshot" }

+ Response 400 (application/json)
Invalid request

    + Body

            {
                "type":      "invalidRequest",
                "httpStatus": 400,
                "message":   "An invalid request was made"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/invalidRequestError" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 404 (application/json)
The specified resource was not found

    + Body

            {
                "type":      "resourceNotFound",
                "httpStatus": 404,
                "message":   "The requested resource was not found"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/resourceNotFoundError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }

### Attach [POST /volumes/{service}/{volumeID}?{attach}]
Attaches the volume to an instance.

+ Parameters

    + service: `ebs-00` (string, required)

        The name of the service to which the Volume belongs

    + volumeID: `vol-000` (string, required)

        The volume's unique ID

    + attach (required)

        The operation flag indicating the attach operation

+ Request (application/json)

    + Attributes

        + nextDeviceName (string, optional) - The next device name
        + opts (object) - Optional request data

    + Headers

            Libstorage-Instanceid: ebs-00=i-123,region%3Dwest

    + Body

            {
                "nextDeviceName": "/dev/xvd02"
            }

+ Response 205
Reset the view of the modified resource

    + Schema

+ Response 400 (application/json)
Invalid request

    + Body

            {
                "type":      "invalidRequest",
                "httpStatus": 400,
                "message":   "An invalid request was made"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/invalidRequestError" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 404 (application/json)
The specified resource was not found

    + Body

            {
                "type":      "resourceNotFound",
                "httpStatus": 404,
                "message":   "The requested resource was not found"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/resourceNotFoundError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }


### Detach [POST /volumes/{service}/{volumeID}?{detach}]
Detaches the volume.

+ Parameters

    + service: `ebs-00` (string, required)

        The name of the service to which the Volume belongs

    + volumeID: `vol-000` (string, required)

        The volume's unique ID

    + detach (required)

        The operation flag indicating the detach operation

+ Request (application/json)

    + Attributes

        + opts (object) - Optional request data

+ Response 200 (application/json)
The volume that was just detached.

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/volume" }

+ Response 400 (application/json)
Invalid request

    + Body

            {
                "type":      "invalidRequest",
                "httpStatus": 400,
                "message":   "An invalid request was made"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/invalidRequestError" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 404 (application/json)
The specified resource was not found

    + Body

            {
                "type":      "resourceNotFound",
                "httpStatus": 404,
                "message":   "The requested resource was not found"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/resourceNotFoundError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }

## Remove [DELETE /volumes/{service}/{volumeID}?{force}]
Removes the volume.

+ Parameters

    + service: `ebs-00` (string, required)

        The name of the service to which the Volume belongs

    + volumeID: `vol-000` (string, required)

        The volume's unique ID

    + force (optional)

        A flag that indicates whether or not this is a force delete. If true
        the delete operation should remove the volume regardless of its state
        or contents.

+ Request (application/json)

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/volumeRemoveRequest" }

+ Response 205
Reset the view of the modified resource

    + Schema

+ Response 400 (application/json)
Invalid request

    + Body

            {
                "type":      "invalidRequest",
                "httpStatus": 400,
                "message":   "An invalid request was made"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/invalidRequestError" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 404 (application/json)
The specified resource was not found

    + Body

            {
                "type":      "resourceNotFound",
                "httpStatus": 404,
                "message":   "The requested resource was not found"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/resourceNotFoundError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }

# Group Snapshots
A collection of resources and actions related to libStorage Snapshots.

# Snapshots Collection [/snapshots]
A collection of Snapshot objects for all configured services.

## Get [GET]
Gets a list of Snapshot resources for all configured services.

+ Response 200 (application/json)

    + Body

            {
                "ebs-00": {
                    "snap-000": {
                        "id": "snap-000",
                        "name": "Snapshot-000",
                        "description": "A snapshot of Volume-000 (vol-000)",
                        "startTime": 1455826676,
                        "volumeID": "vol-000",
                        "volumeSize": 10240,
                        "fields": {
                            "sparse": true,
                            "region": "US"
                        }
                    },
                    "snap-001": {
                        "id": "snap-001",
                        "name": "Snapshot-001",
                        "description": "A snapshot of Volume-000 (vol-000)",
                        "startTime": 1455846531,
                        "volumeID": "vol-000",
                        "volumeSize": 10240,
                        "fields": {
                            "sparse": true,
                            "region": "US"
                        }
                    }
                },
                "ebs-01": {
                    "snap-000": {
                        "id": "snap-000",
                        "name": "Snapshot-000",
                        "description": "A snapshot of Volume-000 (vol-000)",
                        "startTime": 1455826676,
                        "volumeID": "vol-000",
                        "volumeSize": 10240,
                        "fields": {
                            "sparse": true,
                            "region": "US"
                        }
                    }
                }
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/serviceSnapshotMap" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }

# Snapshots by Service Collection [/snapshots/{service}]
A collection of Snapshot resources that belong to Volumes for a specifc service.

+ Parameters

    + service: `ebs-00` (string, required)

        The service name

## Get [GET]
Gets a list of Snapshot objects for a single Service resource.

+ Response 200 (application/json)

    + Body

            {
                "snap-000": {
                    "id":           "snap-000",
                    "name":         "Snapshot-000",
                    "description":  "A snapshot of Volume-000 (vol-000)",
                    "startTime":    1455826676,
                    "volumeID":     "vol-000",
                    "volumeSize":   10240,
                    "fields":       {
                        "sparse":   true,
                        "region":   "US"
                    }
                },
                "snap-001": {
                    "id":           "snap-001",
                    "name":         "Snapshot-001",
                    "description":  "A snapshot of Volume-000 (vol-000)",
                    "startTime":    1455846531,
                    "volumeID":     "vol-000",
                    "volumeSize":   10240,
                    "fields":       {
                        "sparse":   true,
                        "region":   "US"
                    }
                }
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/snapshotMap" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 404 (application/json)
The specified resource was not found

    + Body

            {
                "type":      "resourceNotFound",
                "httpStatus": 404,
                "message":   "The requested resource was not found"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/resourceNotFoundError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }

## Create [POST]
Please note, that the Snapshot Collection resource is not used for the creation
of snapshots. Instead please see the documentation for the Volume Inspector for
how to create snapshots from existing volumes.

Invoking this method will always result in an error.

+ Response 400 (application/json)
Invalid request

    + Body

            {
                "type":      "invalidRequest",
                "httpStatus": 400,
                "message":   "An invalid request was made"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/invalidRequestError" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 404 (application/json)
The specified resource was not found

    + Body

            {
                "type":      "resourceNotFound",
                "httpStatus": 404,
                "message":   "The requested resource was not found"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/resourceNotFoundError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }

# Snapshot Inspector [/snapshots/{service}/{snapshotID}]
A single Snapshot object. A central part of the libStorage API, a Snapshot
resource represents a snapshot of a storage volume.

+ Parameters

    + service: `ebs-00` (string, required)

        The service name

    + snapshotID: `snap-000` (string, required)

        The snapshot's unique ID

## Get [GET]
Retrieves a single snapshot.

+ Response 200 (application/json)

    + Body

            {
                "id":           "snap-000",
                "name":         "Snapshot-000",
                "description":  "A snapshot of Volume-000 (vol-000)",
                "startTime":    1455826676,
                "volumeID":     "vol-000",
                "volumeSize":   10240,
                "fields":       {
                    "sparse":   true,
                    "region":   "US"
                }
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/snapshot" }

+ Response 400 (application/json)
Invalid request

    + Body

            {
                "type":      "invalidRequest",
                "httpStatus": 400,
                "message":   "An invalid request was made"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/invalidRequestError" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 404 (application/json)
The specified resource was not found

    + Body

            {
                "type":      "resourceNotFound",
                "httpStatus": 404,
                "message":   "The requested resource was not found"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/resourceNotFoundError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }

### Copy [POST /snapshots/{service}/{snapshotID}?{copy}]
Copies the snapshot.

+ Parameters

    + service: `ebs-00` (string, required)

        The name of the service to which the Volume belongs

    + snapshotID: `snap-000` (string, required)

        The snapshot's unique ID

    + copy (required)

        The operation flag indicating the copy operation

+ Request (application/json)

    + Body

            {
                "snapshotName": "Copy of Snapshot-000",
                "destinationID": "ebs-01"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/snapshotCopyRequest" }

+ Response 200 (application/json)

    + Attributes (Snapshot)

    + Body

            {
                "id":           "snap-002",
                "name":         "Copy of Snapshot-000",
                "description":  "A copy of the snapshot of Volume-000 (vol-000)",
                "startTime":    1455826676,
                "volumeID":     "vol-000",
                "volumeSize":   10240,
                "fields":       {
                    "sparse":   true,
                    "region":   "US"
                }
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/snapshot" }

+ Response 400 (application/json)
Invalid request

    + Body

            {
                "type":      "invalidRequest",
                "httpStatus": 400,
                "message":   "An invalid request was made"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/invalidRequestError" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 404 (application/json)
The specified resource was not found

    + Body

            {
                "type":      "resourceNotFound",
                "httpStatus": 404,
                "message":   "The requested resource was not found"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/resourceNotFoundError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }

## Remove [DELETE]
Removes the snapshot.

+ Request (application/json)

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/snapshotRemoveRequest" }

+ Response 205
Reset the view of the modified resource

    + Schema

+ Response 400 (application/json)
Invalid request

    + Body

            {
                "type":      "invalidRequest",
                "httpStatus": 400,
                "message":   "An invalid request was made"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/invalidRequestError" }

+ Response 401 (application/json)
Unauthorized request

    + Body

            {
                "type":      "unauthorizedRequest",
                "httpStatus": 401,
                "message":   "The requestor is unauthorized to access this resource"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/unauthorizedRequestError" }

+ Response 404 (application/json)
The specified resource was not found

    + Body

            {
                "type":      "resourceNotFound",
                "httpStatus": 404,
                "message":   "The requested resource was not found"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/resourceNotFoundError" }

+ Response 500 (application/json)
Internal server error

    + Body

            {
                "type":      "internalServerError",
                "httpStatus": 500,
                "message":   "An internal server error occurred"
            }

    + Schema

            { "$ref": "https://raw.githubusercontent.com/rexray/rexray/master/libstorage/libstorage.json#/definitions/internalServerError" }

# Data Structures

## InstanceID (object)
An InstanceID identifies a host to a remote storage platform.

### Properties
+ id (string, required) - The instance ID.
+ data (object, optional) - Extra information about the instance ID.

## ServiceInfo (object)
The ServiceInfo object contains informationa about a configured service.

### Properties
+ name (string, required) - The service name
+ driver (DriverInfo, required) - The name of the driver used by the service

## DriverInfo (object)
The DriverInfo object contains information about a registered driver.

### Properties
+ name (string, required)
+ type (object, required)
+ nextDevice (NextDeviceInfo)

## NextDeviceInfo (object)
NextDeviceInfo assists the libStorage client in determining the
next available device name by providing the driver's device prefix and
optional pattern.

For example, the Amazon Web Services (AWS) device prefix is "xvd" and its
pattern is "[a-z]". These two values would be used to determine on an EC2
instance where "/dev/xvda" and "/dev/xvdb" are in use that the next
available device name is "/dev/xvdc".

If the Ignore field is set to true then the client logic does not invoke the
GetNextAvailableDeviceName function prior to submitting an AttachVolume
request to the server.

### Properties
+ ignore (boolean)
+ prefix (string)
+ pattern (string)

## Volume (object, fixed)
A single Volume object. A central part of the libStorage
API, a Volume resource represents a backend storage
volume.

### Properties
+ id (string, required) - The volume ID.
+ name (string, required) - The volume name.
+ type (string) - The volume type.
+ attachments (array, optional) - The volume's attachments.
    + (VolumeAttachment)
+ availabilityZone (string) - The zone for which the volume is available.
+ iops (number) - The volume IOPs.
+ networkName (string) - The name of the network on which the volume resides.
+ size (number, required) - The volume size (GB).
+ status (string) - The volume status.
+ fields (object) - Fields are additional properties that can be defined for this type.

## VolumeAttachment (object, fixed)
A single VolumeAttachment object contains information about a resource attached
to a storage volume.

### Properties
+ deviceName (string, required) - The name of the device on which the volume to which the object is attached is mounted.
+ instanceID (InstanceID, required) - The ID of the instance on which the volume to which the attachment belongs is mounted.
+ status (string) - The status of the attachment.
+ volumeID (string, required) - The ID of the volume to which the attachment belongs.
+ fields (object) - Fields are additional properties that can be defined for this type.

## Snapshot (object, fixed)
A single Snapshot object. Created by invoking the snapshot operation on a
Volume, the Snapshot resource can also be copied and used as the basis for
a new Volume resource.

### Properties
+ id (string, required) - The snapshot ID.
+ name (string, required) - The snapshot name.
+ description (string, required) - The snapshot description.
+ startTime (number, required) - The time (epoch) at which the request to create the snapshot was submitted.
+ status (string) - The volume status.
+ volumeID (string, required) - The ID of the volume to which the snapshot is linked.
+ volumeSize (number, required) - The size (GB) of the volume to which the snapshot is linked.
+ fields (object) - Fields are additional properties that can be defined for this type.
